home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
MacWorld 1997 September
/
Macworld (1997-09).dmg
/
Shareware World
/
Utilities
/
Text Processing
/
Alpha
/
Tcl
/
UserCode
/
vi.tcl
< prev
Wrap
Text File
|
1994-05-30
|
18KB
|
680 lines
# Alpha 5.x Init File
# ****************************************************************************
# FILE: vi.tcl
# CONTENTS: Alpha tcl startup for simple "vi" emulation.
# AUTHOR: Peter H. Mills (phm@cs.duke.edu)
# COPYRIGHT:
# Copyright © 1994 by Peter H. Mills
# All rights reserved.
#
# Redistribution and use in source and binary forms are permitted
# provided that the above copyright notice and this paragraph are
# duplicated in all such forms and that any documentation,
# advertising materials, and other materials related to such
# distribution and use acknowledge that the software was developed
# by Peter H. Mills.
#
# THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
# IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
# ***************************************************************************
# ==========================================
# ==== Vi MODE (Vi, Insert, Ex) ====
# ==========================================
# VI (visual editor --- minimal subset) --- by Peter Mills
#
# INTRODUCTION:
# This is a tcl package for Alpha that supports a subset of vi mode
# and an extremely small set of ex commands.
# USAGE:
# You should "source" this file in your userStartup.tcl file.
# (See AlphaBits.tcl for an example of "source" command usage).
# The file will automatically add an entry for "Vi" to the mode menu
# (the lower left-hand window box), which allows you to enter vi mode.
# (Alternatively, to enter vi mode execute the command "setViMode";
# to exit vi mode simply use the normal Alpha mode switching technique.)
# To have vi mode entered automatically on file open, you must
# alter the "setWinMode{}" function in SystemCode:procs.tcl
# which chooses the mode based on recognizing file suffixes
# (or, if using Mills' advanced "modeprocs.tcl" and "modes.tcl",
# by overriding the "modeOfFileName" function in "modes.tcl").
# SUMMARY of vi COMMANDS supported:
# MODE SWITCH: i (insert mode)
# ESC (end insert mode, or abort in vi mode),
# : (ex mode -- very limited, don't use it).
# ^z (switch from vi mode to text mode)
# MOTION: h,j,k,l,0,$, DEL (backward), CR (nextline), ^f, ^b,
# w,b,e,z, ^1 (home), ^$ (lastline)
# EDITING: c<w,$> i a A o O s
# d<w,$,d,L> x J ("r" == s) d<R=rest,B=before>
# MARKS: m (set named mark) ' (goto named mark)
# ^m (set mark) ^' (exchangePointAndMark)
# CUT & PASTE: p (yank) dx (cut) dc (copy) dv (paste)
# SEARCH: / (forward) ? (backward) n (find next)
# ^% (balance, matchbrace)
# UNDO/REDO: u undo (history)
# . redo (ONLY on "d" and insert-ops <c,i,A,o>)
# (Redo lastcommand above, ignores intervening history.
# STATUS: ^g
# EX mode:
# MOTION: 1 (home) $ (end) g (goto line)
# CUT & PASTE: x (cut) c (copy) v (paste)
# X (cut named clipb) C (copy named) V (paste named)
# FILE and WINDOW: q (quit) r (read) w (save) n (new win) s (save As)
# S (save selection) p (copy sel to new wind)
# *****************************************************************************
# ==========================================
# ==== Vi MODE (Vi, Insert, Ex) ====
# ==========================================
# Vi Mode:
# Variables
# Functions: Edit
# Functions: Mode
# Key Bindings: Vi, Insert, Ex Modes
#===========================================
# ==========================
# ==== VARIABLES
# ==========================
# ==== Constants ====
set esc 0x35
set del 0x33
set cr 0x24
set spc 0x31
set quot 0x27
if {! [info exists altesc]} { set altesc 0x35 }
# ==== Redo History ====
set viLastCmd ""
set viInsertText ""
# ==== Search Params ====
set searchStr ""
set searchWrap 1
set forward 1
set regExpr 1
set ignoreCase 1
set matchWords 0
# =====================================================================
# ==========================
# ==== MODE FUNCTIONS ====
# ==========================
#=========================================================
# COPIED from modeprocs.tcl (by Peter Mills)
# DEPENDENCES: changeMode(mode), winNameToNum(name)
#====
# SUBMODE is name, used by "displayMode", of a set of KEY BINDINGS.
#====
if {! [info exists modeprocs_defined]} {
set curWinId -1
set subMode ""
proc changeSubMode {newSubMode {wname ""}} {
global subMode
global curWinId
global winNumToSubMode
set curWinName [lindex [winNames -f] 0]
set curWinId [getWinId $curWinName]
if {$wname == ""} { set winId $curWinId
} else { set winId [getWinId $wname] }
if {$winId >= 0} { set winNumToSubMode($winId) $newSubMode }
if {$winId != $curWinId} { return }
displayMode $newSubMode
set subMode $newSubMode
}
proc getWinId wname {
global winNameToNum
if {[catch { set winId $winNameToNum($wname) }]} { set winId -1 }
return $winId
}
proc addMode {mode modeProc modeWinFunc modeMenu} {
global modes
global modeProcs modeWinFuncTitle modeAddMenu
lappend modes $mode
set modeProcs($mode) $modeProc
set modeWinFuncTitle($mode) $modeWinFunc
set modeAddMenu($mode) $modeMenu
}
}
#=========================================================
catch {
if {([info exists modes]) && ([lsearch -exact $modes "Vi"] < 0)} {
addMode Vi setViMode "Func" "" }
}
#====
# ==== SUBMODE (Minor Mode)
#
# WARNING: viSubMode, viInsertText should be BUFFER LOCAL (curWinId)
#
# "subMode" from modes.tcl, *is* buffer local -- changeSubMode().
#====
# ==== SWITCH to VI Command Mode ====
proc viCmdMode {} { changeSubMode "Vi" }
# changeMode: restores mode-local params, sets 1st time to TextModeParams
proc setViMode {} {
changeMode "Vi"
uplevel #0 {
set wordBreak "$viWordBreak"
set wordBreakPreface "$viWordBreakPreface"
}
viCmdMode
}
proc setViModeOff {} {
message "Exiting vi mode"
changeMode "Text"
}
proc viRedoLastCmd {} {
global viLastCmd
global subMode
if {$viLastCmd == ""} {
abortEm
return
}
set subMode "Vi"
$viLastCmd
if {$subMode == "Insert"} { viRedoInsert }
}
# ==== SWITCH to VI Insert Mode ====
proc viInsertCmd {} {
global viLastCmd
global curWinId
changeSubMode "Insert"
set viLastCmd viInsertCmd
if {[getPos] != [selEnd]} { deleteText [getPos] [selEnd] }
createTMark "viIns$curWinId" [getPos]
}
proc viInsertMode {} {
global curWinId
changeSubMode "Insert"
createTMark "viIns$curWinId" [getPos]
}
# END INSERT: save inserted text in insert-buffer, switch to VI Command Mode.
# PROBLEM: "viIns" mark may be gone via deletion past insert-point (~bind redo)
proc viEndInsMode {} {
global viInsertText
global curWinId
# # (viCmdMode)
changeSubMode "Vi"
set end [getPos]
if [catch { gotoTMark "viIns$curWinId" }] { beep ; return }
# # removeTMark "viIns$curWinId" --- auto at win close
set start [getPos]
goto $end
if {$start >= $end} { return }
set viInsertText [getText $start $end]
}
proc viRedoInsert {} {
global viInsertText
if {[getPos] == [selEnd]} { insertText $viInsertText
} else { replaceText [getPos] [selEnd] $viInsertText }
viCmdMode
}
# ==== SWITCH to vi EX Mode ====
proc viExMode {} {
changeSubMode "Ex"
message "ex Mode"
}
# =====================================================================
# ==========================
# ==== EDIT FUNCTIONS (WORD MOTION)
# ==========================
set viWordBreak {(([a-zA-Z0-9_]+)|([!-/:-@\[-^\`\{-~]+))}
set viWordBreakPreface {([^a-zA-Z0-9_])}
set viSWordBreakPreface \
{(([^a-zA-Z0-9_]([a-zA-Z0-9_]+))|([^!-/:-@\[-^\`\{-~]([!-/:-@\[-^\`\{-~]+)))}
set viNonWhiteSpace {[!-~]}
proc viEndOfWord {} {
global viWordBreak
set retval [search -f 1 -r 1 -i 1 -m 0 -n "$viWordBreak" [getPos]]
if {($retval != "")} {
set retval [lindex $retval 1]
goto $retval }
}
proc viBackwardWord {} {
global viSWordBreakPreface
set start [getPos]
if {($start > 1)} { incr start -2 }
set retval [search -f 0 -r 1 -i 1 -m 0 -n "$viSWordBreakPreface" $start]
if {($retval != "")} {
set retval [lindex $retval 0]
goto $retval
forwardChar }
}
proc viForwardWord {} {
global viSWordBreakPreface
set retval [search -f 1 -r 1 -i 1 -m 0 -n "$viSWordBreakPreface" [getPos]]
if {($retval != "")} {
set retval [lindex $retval 0]
goto $retval
forwardChar }
}
# ==========================
# ==== EDIT FUNCTIONS ====
# ==========================
proc viDeleteCharX {} {
set start [getPos]
set point_max [maxPos]
if {($start >= $point_max) || ([lookAt [getPos]] == "\n") ||
([lookAt [getPos]] == "\r")} { backwardChar }
deleteChar
}
proc viDeleteCharB {} {
backwardChar
deleteChar
}
proc viDeleteCharSel {} {
if {[getPos] == [selEnd]} {
backwardChar
deleteChar
} else { deleteText [getPos] [selEnd] }
}
proc viTypeSpace {} {
insertText " "
}
proc viYank {} {
global viLastCmd
set viLastCmd viYank
endOfLine
yank
beginningOfLine
}
proc viJoinLine {} {
global viLastCmd
global viNonWhiteSpace
set viLastCmd viJoinLine
createTMark "viTmp" [getPos]
endOfLine
deleteChar
# # STRIP WHITE SPACE
set start [getPos]
set retval [search -f 1 -r 1 -i 1 -m 0 -n "$viNonWhiteSpace" $start]
if {($retval != "")} { set retval [lindex $retval 0]
} else { set retval $start }
if {$start < $retval} { deleteText $start $retval }
#
insertText " "
gotoTMark "viTmp"
removeTMark "viTmp"
}
proc viOpenLine {} {
global viLastCmd
set viLastCmd viOpenLine
endOfLine
carriageReturn
viInsertMode
}
proc viOpenLineB {} {
openLine
viInsertMode
}
proc viDeleteLineEnd {} {
global viLastCmd
set viLastCmd viDeleteLineEnd
set start [getPos]
endOfLine
deleteText $start [getPos]
}
proc viDeleteLine {} {
global viLastCmd
set viLastCmd viDeleteLine
endOfLine
set end [getPos]
previousLine
endOfLine
deleteText [getPos] $end
beginningOfLine
nextLine
}
proc viDeletePage {} {
global viLastCmd
set viLastCmd viDeletePage
set start [getPos]
pageForward
moveInsertionHere
deleteText $start [getPos]
}
proc viDeleteRest {} {
global viLastCmd
set viLastCmd ""
set start [getPos]
endOfBuffer
deleteText $start [getPos]
}
proc viDeleteAllBefore {} {
global viLastCmd
set viLastCmd ""
set end [getPos]
beginningOfBuffer
deleteText [getPos] $end
}
proc viDeleteWord {} {
global viLastCmd
set viLastCmd viDeleteWord
set start [getPos]
viForwardWord
set end [getPos]
if {$start < $end} { deleteText $start $end }
}
proc viAdd {} {
global viLastCmd
set viLastCmd viAdd
viForwardWord
viInsertMode
}
proc viAddEnd {} {
global viLastCmd
set viLastCmd viAddEnd
endOfLine
viInsertMode
}
proc viChangeLine {} {
global viLastCmd
set viLastCmd viChangeLine
set start [getPos]
endOfLine
select $start [getPos]
viInsertMode
}
proc viChangeWord {} {
global viLastCmd
set viLastCmd viChangeWord
set start [getPos]
viEndOfWord
select $start [getPos]
viInsertMode
}
proc viSubChar {} {
global viLastCmd
set viLastCmd viSubChar
set start [getPos]
set end $start
incr end
select $start $end
viInsertMode
}
# Search with Wrap (searchWrap) ;
# Max_Position(File) = {0,[maxPos]-1}
proc viSearch {} {
global searchStr
global searchWrap
global forward
set start [getPos]
set point_max [expr {[maxPos] - 1}]
if {$forward} { if {($start < $point_max)} { incr start }
} else { if {$start > 0} { incr start -1 } }
set retval [search -f $forward -n -- "$searchStr" $start]
if {($retval == "") && $searchWrap} {
if {$forward} { set frompos 0 } else { set frompos $point_max }
if {$forward} {
set retval [search -f $forward -n -l $start -- "$searchStr" $frompos]
} else {
set retval [search -f $forward -n -- "$searchStr" $frompos]
if {($retval != "") && ([lindex $retval 0] < $start)} {
set retval ""} }
}
if {$retval == ""} { beep } else { goto [lindex $retval 0] }
}
proc viSearchBackward {} {
global searchStr
global forward
if [catch { prompt "Search for: " $searchStr } retval] { return }
set forward 0
set searchStr $retval
viSearch
}
proc viSearchForward {} {
global searchStr
global forward
if [catch { prompt "Search for: " $searchStr } retval] { return }
set forward 1
set searchStr $retval
viSearch
}
proc viRedoSearch {} {
global forward
if {$forward} { repeatSearchForward } else { repeatSearchBackward }
}
proc viCopySelWind {} {
if {[getPos] == [selEnd]} { return }
set text [getText [getPos] [selEnd]]
new
moveInsertionHere
insertText $text
}
# (view named clipboard, copy and view clipboard)
# ==== save selection to file ====
proc viSaveSelection {} {
viCopySelWind
saveAs
killWindow
}
# =====================================================================
# ==========================
# ==== KEY BINDINGS ====
# ==========================
# ==== BINDINGS for EMACS (deleted from original) ====
# bind 'j' <e> fillRegion
# bind 'p' <e> fillParagraph
# bind '<' <se> beginningOfBuffer
# bind '>' <se> endOfBuffer
bind 'z' <z> setViMode
# ==================================
# ==== INSERT MODE BINDINGS ====
# ==================================
bind $esc viEndInsMode "Insert"
bind $altesc viEndInsMode "Insert"
bind $del viDeleteCharSel "Insert"
bind $del <s> viDeleteCharSel "Insert"
bind '\n' carriageReturn "Insert"
bind '\n' <s> carriageReturn "Insert"
bind '\r' carriageReturn "Insert"
bind '\r' <s> carriageReturn "Insert"
bind $spc viTypeSpace "Insert"
bind $spc <s> viTypeSpace "Insert"
bind 'z' <z> setViModeOff "Insert"
# ==========================
# ==== VI MODE BINDINGS ====
# ==========================
# ESC==abort (reset so not void redo "viIns"), ' '==special
# DEL==backwardChar (vs. backSpace)
bind $esc abortEm "Vi"
bind $altesc abortEm "Vi"
bind $del viDeleteCharSel "Vi"
bind $del <s> viDeleteCharSel "Vi"
bind '\n' nextLine "Vi"
bind '\n' <s> nextLine "Vi"
bind '\r' nextLine "Vi"
bind '\r' <s> nextLine "Vi"
bind $spc forwardChar "Vi"
bind $spc <s> forwardChar "Vi"
bind 'i' viInsertCmd "Vi"
bind ':' <s> viExMode "Vi"
bind 'z' <z> setViModeOff "Vi"
bind '\' startEscape "Vi"
bind '\' <e> evalCommand "Vi"
bind 'a' viAdd "Vi"
bind 'a' <s> viAddEnd "Vi"
bind 'b' viBackwardWord "Vi"
bind 'c' prefixChar "Vi"
bind 'd' prefixChar "Vi"
bind 'e' viEndOfWord "Vi"
bind 'g' currentPosition "Vi"
bind 'h' backwardChar "Vi"
bind 'j' nextLine "Vi"
bind 'j' <s> viJoinLine "Vi"
bind 'k' previousLine "Vi"
bind 'l' forwardChar "Vi"
bind 'm' setNamedMark "Vi"
bind 'n' viSearch "Vi"
bind 'o' viOpenLine "Vi"
bind 'o' <s> viOpenLineB "Vi"
bind 'p' viYank "Vi"
bind 'r' viSubChar "Vi"
bind 's' viSubChar "Vi"
bind 't' viEndOfWord "Vi"
bind 'u' undo "Vi"
bind 'v' viBackwardWord "Vi"
bind 'w' viForwardWord "Vi"
bind 'x' viDeleteCharX "Vi"
bind 'y' yank "Vi"
bind 'z' insertToTop "Vi"
bind '0' beginningOfLine "Vi"
bind '%' <s> balance "Vi"
bind '$' <s> endOfLine "Vi"
bind $quot gotoNamedMark "Vi"
bind '/' viSearchForward "Vi"
bind '?' <s> viSearchBackward "Vi"
#====
# ' marks (^' for '')
# m: named mark (^m for set current mark)
# n: repeatSearchForward (redo commands (persistent))
# d: <x> w or $
# c: <e> w or $
#====
# ==================================================================
# ==== VI MODE BINDINGS -- PERMANENT (prefixed) SETTINGS ====
# ==================================================================
bind 'a' <z> beginningOfLine "Vi"
bind 'b' <z> pageBack "Vi"
bind 'e' <z> endOfLine "Vi"
bind 'f' <z> pageForward "Vi"
bind 'g' <z> currentPosition "Vi"
bind 'h' <z> backwardChar "Vi"
bind 'j' <z> nextLine "Vi"
bind 'k' <z> previousLine "Vi"
bind 'l' <z> forwardChar "Vi"
bind 'n' <z> scrollDownLine "Vi"
bind 'p' <z> scrollUpLine "Vi"
bind 'q' <z> keyAscii "Vi"
bind 'r' <z> fillParagraph "Vi"
# REGION SELECT/EDIT
bind 't' <z> viEndOfWord "Vi"
bind 'u' <z> undo "Vi"
bind 'v' <z> viBackwardWord "Vi"
bind 'w' <z> viForwardWord "Vi"
bind 'y' <z> viYank "Vi"
bind '1' <z> beginningOfBuffer "Vi"
bind '4' <z> endOfBuffer "Vi"
bind '5' <z> balance "Vi"
bind '.' viRedoLastCmd "Vi"
# . : redo command (history sensitive)
# ==== DELETE MODE MODIFIERS (d prefix)
bind 'd' <z> prefixChar "Vi"
bind 'x' <D> cut "Vi"
bind 'c' <D> copy "Vi"
bind 'v' <D> paste "Vi"
bind 'w' <D> viDeleteWord "Vi"
bind 'd' <D> viDeleteLine "Vi"
bind '$' <sD> viDeleteLineEnd "Vi"
bind 'L' <sD> viDeletePage "Vi"
bind 'R' <sD> viDeleteRest "Vi"
bind 'B' <sD> viDeleteAllBefore "Vi"
# ==== CHANGE MODE MODIFIERS (c prefix)
bind 'c' <z> prefixChar "Vi"
bind 'w' <C> viChangeWord "Vi"
bind '$' <Cs> viChangeLine "Vi"
# === MARK MODE MODIFIERS (^') ====
bind $quot <z> exchangePointAndMark "Vi"
bind 'm' <z> setMark "Vi"
bind '^' <z> exchangePointAndMark "Vi"
bind '@' <z> setMark "Vi"
# ==========================
# ==== EX MODE BINDINGS ====
# ==========================
bind $esc viCmdMode "Ex"
bind $altesc viCmdMode "Ex"
bind $del viDeleteCharB "Ex"
bind $del <s> viDeleteCharB "Ex"
bind '\n' viCmdMode "Ex"
bind '\n' <s> viCmdMode "Ex"
bind '\r' viCmdMode "Ex"
bind '\r' <s> viCmdMode "Ex"
bind 'z' <z> setViModeOff "Ex"
bind 'c' copy "Ex"
bind 'c' <s> copyNamedClipboard "Ex"
bind 'g' gotoLine "Ex"
bind 'n' new "Ex"
bind 'p' viCopySelWind "Ex"
bind 'q' killWindow "Ex"
bind 'r' insertFile "Ex"
bind 's' saveAs "Ex"
bind 's' <s> viSaveSelection "Ex"
bind 'v' paste "Ex"
bind 'v' <s> pasteNamedClipboard "Ex"
bind 'w' save "Ex"
bind 'x' cut "Ex"
bind 'x' <s> cutNamedClipboard "Ex"
bind '1' beginningOfBuffer "Ex"
bind '$' <s> endOfBuffer "Ex"
# ***************************************************************************
# END of VI section.
# ***************************************************************************
#===================================
# ==== EMACS MODE BINDINGS ====
#===================================
#======================== END NUMLINES 777 ====================================